package com.example.oauth2.utils;

import com.example.oauth2.enums.CustomOAuth2TokenClaimNames;
import com.example.oauth2.enums.CustomScopes;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;

import java.security.Principal;
import java.util.*;
import java.util.function.Consumer;

/**
 * @author <a href="nav1cat@outlook.com">nav1c</a>
 * @apiNote
 * @date 2024-02-07 19:30:39
 * @project study-cloud
 * @kit IntelliJ IDEA
 */
public final class TokenClaimsUtils {

    private TokenClaimsUtils(){
        throw new IllegalStateException("");
    }

    public static void embedUserAuthorities(Collection<GrantedAuthority> authorities, Map<String, Object> claims){
        Object o1 = claims.get(OAuth2TokenIntrospectionClaimNames.SCOPE);
        Object o2 = claims.get(CustomOAuth2TokenClaimNames.AUTHORITIES);
        if (o1 instanceof Collection<?> scopes && o2 instanceof Collection<?> stringAuthorities
                && scopes.contains(CustomScopes.USER_AUTHORITY)){
            stringAuthorities.forEach(e -> authorities.add(new SimpleGrantedAuthority(Objects.toString(e))));
        }
    }

    public static Consumer<Map<String, Object>> customizerUserAuthorities(Set<String> authorizedScopes, Principal principal) {
        if (authorizedScopes != null && authorizedScopes.contains(CustomScopes.USER_AUTHORITY)
                && principal instanceof UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken){
                Collection<GrantedAuthority> authorityCollection = usernamePasswordAuthenticationToken.getAuthorities();
                if (authorityCollection != null) {
                    final Set<String> authorities = new LinkedHashSet<>();
                    authorityCollection.forEach(grantedAuthority -> authorities.add(grantedAuthority.getAuthority()));
                    return stringObjectMap ->
                            stringObjectMap.put(CustomOAuth2TokenClaimNames.AUTHORITIES, Collections.unmodifiableSet(authorities));
                }
        }
        return stringObjectMap -> {};
    }
}
